/*
 * Copyright (C) Francisco Morero Peyrona. All rights reserved.
 *
 * This software is published under the terms of Open Source
 * License version 1.1, a copy of which has been included with this
 * distribution in the License.txt file.
 */

package jdbcmanager.dbtools.datatypes;

import java.util.Hashtable;

import jdbcmanager.dbtools.DbUtil;

/**
 * This class is an struct of data that represents a Field of a table.
 *
 * @author Francisco Morero Peyrona
 */
public final class TableColumnDefinition
{
   private String                    sName;
   private TableColumnTypeDefinition oType;
   private int                       nSize;
   private int                       nScale;
   private boolean                   bNullable;
   private boolean                   bAutoInc;
   private boolean                   bPrimaryKey;
   private Object                    oDefault;
   private Hashtable[]               ahtExtraInfo;  // NEXT: Esto se puede utilizar (junto con un SpringLayout) para mostrar las
                                                    // properties especiales q tienen las columnas en cada DBMS (i.e. Description)
   /**
    * Zero argument class constructor.
    */
   public TableColumnDefinition()
   {
      TableColumnTypeDefinition[] aTCTD  = DbUtil.getAgentDBMS().getAgentMetaData().getSupportedColumnTypes();
      int                         nIndex = TableColumnTypeDefinition.searchOnType( aTCTD, java.sql.Types.VARCHAR );   
      
      this.sName        = "NoName";
      this.oType        = aTCTD[ nIndex ];
      this.nSize        = 32;
      this.nScale       =  0;
      this.bNullable    = true;
      this.bAutoInc     = false;
      this.bPrimaryKey  = false;
      this.oDefault     = null;
      this.ahtExtraInfo = new Hashtable[0];
   }

   /**
    * Class constructor
    *
    * @param sName
    * @param nDataType
    * @param nSize
    * @param bNullable
    * @param bAutoIncrement
    * @param bPrimaryKey
    * @param sDescription
    */
   public TableColumnDefinition( String sName, TableColumnTypeDefinition oType, int nSize, int nScale, boolean bNullable, 
                                 boolean bAutoIncrement, boolean bPrimaryKey, Object oDefault )
   {
      setName( sName );
      setType( oType );
      setSize( nSize );
      setScale( nScale );
      setNullable( bNullable );
      setAutoIncrement( bAutoIncrement );
      setPrimaryKey( bPrimaryKey );
      setDefaultValue( oDefault );     
   }

   public String                    getName()            { return this.sName;        }
   public TableColumnTypeDefinition getType()            { return this.oType;        }
   public int                       getSize()            { return this.nSize;        }
   public int                       getScale()           { return this.nScale;       }
   public boolean                   isNullable()         { return this.bNullable;    }
   public boolean                   isAutoIncrement()    { return this.bAutoInc;     }
   public boolean                   isPrimaryKey()       { return this.bPrimaryKey;  }
   public Object                    getDefaultValue()    { return this.oDefault;     }
   public Hashtable[]               getExtraProperties() { return this.ahtExtraInfo; }  // Granted not to be null
   
   /**
    * Column name
    * @param s Column name
    */
   public void setName( String s )                        
   { 
      this.sName = (s == null) ? "NoName" : s.trim();
   }
   
   /**
    * 
    * @param o
    */
   public void setType( TableColumnTypeDefinition o ) 
   { 
      this.oType = o;
      
      // When type changes these values must be re-viewed
      setSize( getSize() );
      setScale( getScale() );
      setNullable( isNullable() );
      setAutoIncrement( isAutoIncrement() );
   }
   
   /**
    * 
    * @param n
    */
   public void setSize( int n )                           
   { 
      if( n < 1 )
         n = 1;
   
      if( n > getType().getPrecision() - getType().getMaxScale() )
         n = getType().getPrecision() - getType().getMaxScale();  // NEXT: probablemente esto no es asi, sino restando getMinScale()
   
      this.nSize = n;
   }
   
   /**
    * Set the number of digits after decimal separator.
    * 
    * @param nScale Number of digits after decimal separator
    */
   public void setScale( int nScale )
   {
      if( nScale < getType().getMinScale() )
         nScale = getType().getMinScale();
      
      if( nScale > getType().getMaxScale() )
         nScale = getType().getMaxScale();
      
      this.nScale = nScale;
   }
   
   /**
    * This column will or will not admit <code>null</code> as a value.
    * <p>
    * Obviously, a <code>true</code> value will accepted only if the type accepts nulls. 
    * 
    * @param b
    */
   public void setNullable( boolean b )                   
   { 
      this.bNullable = b && getType().isNullabe();
   }
   
   /**
    * 
    * @param b
    */
   public void setAutoIncrement( boolean b )         
   { 
      this.bAutoInc = b && getType().isAutoIncrementable();
   }
   
   /**
    * Is this column a primary key column?
    * 
    * @param b
    */
   public void setPrimaryKey( boolean b )
   { 
      this.bPrimaryKey  = b;
   }
   
   /**
    * 
    * @param oValue
    */
   public void setDefaultValue( Object oValue )
   { 
      this.oDefault = oValue;
   }
   
   /**
    * Reserverd for next version (not used)
    * @param aExtra
    */
   public void setExtraProperties( Hashtable[] aExtra )
   {
      if( aExtra == null )
         aExtra = new Hashtable[0];
      
      this.ahtExtraInfo = aExtra;
   }
   
   
    /* (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    public String toString()
    {
        return "TableColumn: [" + sName + "] type: [" + oType + "]";
    }
}